home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d22
/
csap208b.arc
/
SORTDIR.C
< prev
next >
Wrap
Text File
|
1989-10-10
|
10KB
|
341 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <ctype.h>
#include <mem.h>
#include "dosstruc.h"
/*
* SORTDIR is the main routine of CSAP. It is a recursive routine that will
* walk the directory hierarchy, sorting all directories that it finds. It
* uses the quick sort or quicker sort algorithm provided by most C runtime
* libraries to perform the actual sort. It uses DOS Int 25H and 26H,
* Absolute Disk Read and Absolute Disk Write, to read the directories into
* memory for sorting and to write out the sorted directories. It depends
* upon information about the physical characteristics of the disk provided
* by GETDPB.
*/
void SortDir () {
void PutQueue(), GetKey(), qsort();
void ReadSub(), WriteSub(), ReadRoot(), WriteRoot();
char *strrspn();
int strincmp(), SearchFirst();
unsigned al2sec(), NextCl();
extern char Disk, *Fat, Parent[67], Element[13];
extern char Line[80], Level, RSwt, VerSwt, Packed;
extern struct DpbStruct Dpb;
extern struct DirEntry *DirBuff;
extern unsigned Cluster, Sector, NumSec;
extern int Lim, j, l;
extern struct ClusterEntry *p, *t;
extern int OutSectors, OutClusters, BytesPerCluster, ECount;
extern struct ExtFcb Fcb;
extern struct ExtendedEntry Dir;
extern struct ClusterQueue CluQ;
extern int Is12Bit, *CluArray;
extern unsigned MinMem;
char **DirVector, *r, Reply;
int i, k, DirCount, Root;
unsigned Mem;
BytesPerCluster = (Dpb.ClusterSize + 1) * Dpb.SectorSize;
if (strlen(Element) != 0) { /* Sorting a sub-directory */
Root = 0;
bdos(0x3B, (int) Parent, 0); /* Set Current Directory */
if (Parent[strlen(Parent)-1] != '\\') strcat(Parent, "\\");
setdta((char *) &Dir);
parsfnm(Element, (struct fcb *) &Fcb.DriveId, 0);
Fcb.FcbHdr.Header = 0xFF;
Fcb.DriveId = Disk - '@';
Fcb.FcbHdr.Attrib = 0xFF;
if (SearchFirst(&Fcb) != 0) {
fprintf(stderr, "Not found: %s%s\n", Parent, Element);
AbortProgram();
}
}
else Root = 1; /* Sorting the Root directory */
printf("Sorting: %s%s", Parent, Element);
if (!isdevice(1)) fprintf(stderr, "Sorting: %s%s", Parent, Element);
/* Read directory to be sorted into memory */
if (Root) ReadRoot();
else ReadSub();
/* Count sub-directories, skipping "current" and "parent" entries */
for (DirCount=0, i=0; i < Lim / sizeof(struct DirEntry); i++) {
if (DirBuff[i].Name[0] == 0) break;
if ((DirBuff[i].Attribute & 0x10)
&& (DirBuff[i].Name[0] != '.')
&& (DirBuff[i].Name[0] != 0xE5)) DirCount++;
}
k = i;
if (DirCount != 0) {
if ((DirVector = malloc(DirCount * sizeof(DirVector))) == NULL) {
fprintf(stderr, "Insufficient memory (2).\n");
return;
}
}
/*
* Compute the number of directory sectors to write out - don't write sectors
* that don't contain active entries.
*/
OutSectors = ((i * 32) + Dpb.SectorSize - 1) / Dpb.SectorSize;
OutClusters = (OutSectors + Dpb.ClusterSize) >> Dpb.ClusterShift;
j = 0;
if (Root) {
/* If sorting Root - skip 1st two files if "System" & "Hidden" */
if (i > 1) {
if (DirBuff[j].Attribute & 0x06) {
j++; i--;
if (DirBuff[j].Attribute & 0x06) {
j++; i--;
}
}
}
}
else {
/* If sorting subdirectory - skip 1st two entries, "current" and "parent" */
j += 2; i -= 2;
}
if (i == 0) {
printf(" Empty.\n");
r = &Parent[strlen(Parent)-1];
if (r[-1] == ':') r++;
*r = 0x00;
return;
}
/* If VerSwt ON - request operator confirmation BEFORE sorting */
if (VerSwt != 0) {
if (!isdevice(1)) {
fprintf(stderr, " Sort (Y or N)? "); fflush(stderr);
}
else {
printf(" Sort (Y or N)? "); fflush(stdout);
}
if (toupper(getche()) != 'Y') {
if (!isdevice(1)) fprintf(stderr, "n");
printf("\n");
return;
}
}
if (!isdevice(1)) fprintf(stderr, "\n");
printf("\n");
/* Sort directory */
qsort(&DirBuff[j], i, sizeof(struct DirEntry), strincmp);
ECount = 0;
/*
* If Packed OFF, remove "erased" entries from directory (mark them "unused)
*/
if (Packed != 0) {
for (i=k; i >= 0; i--) {
if ((DirBuff[i].Name[0] != 0xE5) && (DirBuff[i].Name[0] != 0x00)) break;
if (DirBuff[i].Name[0] == 0xE5) {
DirBuff[i].Name[0] = 0x00;
++ECount;
}
}
}
/* Build list of subdirectories - skipping "current" and "parent" entries */
for (l=0, i=0; DirBuff[i].Name[0]; i++) {
if ((DirBuff[i].Attribute & 0x10) && (DirBuff[i].Name[0] != '.')) {
for (k=0, j=0; j<8; ++j) {
if (DirBuff[i].Name[j] == ' ') break;
else Line[k++] = DirBuff[i].Name[j];
}
if (DirBuff[i].Ext[0] != ' ') {
Line[k++] = '.';
for (j=0; j<3; ++j) {
if (DirBuff[i].Ext[j] == ' ') break;
else Line[k++] = DirBuff[i].Ext[j];
}
}
Line[k++] = '\0';
if ((DirVector[l] = malloc(k)) == NULL) {
fprintf(stderr, "Insufficient memory.\n");
return;
}
strcpy(DirVector[l++], Line);
}
}
/* Write out sorted directory */
if (Root) {
WriteRoot();
if (RSwt) printf(" Location: %04XH-%04XH\n", Dpb.DirStart, Dpb.DirStart + NumSec - 1);
}
else {
WriteSub();
if (RSwt) {
printf(" Location:");
for (i=0; i<CluQ.Count; ++i) {
if (i == 0) printf(" %04XH", Alu2Sec(&Dpb, CluArray[i]));
if ((i > 0) && (CluArray[i] != CluArray[i-1] + 1)) {
printf("-%04XH %04XH",
Alu2Sec(&Dpb, CluArray[i-1] + 1) - 1,
Alu2Sec(&Dpb, CluArray[i])
);
}
}
printf("-%04XH\n", Alu2Sec(&Dpb, CluArray[i-1] + 1) - 1);
}
}
if (RSwt) printf(" %d Erased entries removed\n", ECount);
Mem = coreleft();
if (MinMem < Mem) MinMem = Mem;
/* Release dynamically acquired space for this directory */
free(DirBuff);
for (p = CluQ.Head; p != NULL; p = t) {
t = p->Next; free(p);
}
free(CluArray);
/* If Recursive sort - build Parent and Element for sub directories & sort */
if (!Level) {
strcat(Parent, Element);
for (i=0; i < DirCount; i++) {
strcpy(Element, DirVector[i]);
SortDir();
}
r = strrspn(Parent, "\\/");
if (r[-1] == ':') r++;
*r = 0x00;
}
}
void ReadSub() {
extern unsigned Cluster;
extern unsigned LastCluster;
extern char *Fat;
extern struct ExtendedEntry Dir;
extern struct ClusterQueue CluQ;
extern int Is12Bit, *CluArray, BytesPerCluster, Lim;
extern char Disk, *Fat;
extern struct DirEntry *DirBuff;
extern struct DpbStruct Dpb;
int i;
struct ClusterEntry *p;
void PutQueue();
unsigned NextCl();
Cluster = Dir.Body.FirstCluster;
CluQ.Head = CluQ.Current = NULL; CluQ.Count = 0;
while (Cluster < LastCluster) {
PutQueue(&CluQ, Cluster);
Cluster = NextCl(Is12Bit, Cluster, Fat);
}
if ((CluArray = malloc(CluQ.Count * sizeof(int))) == NULL) {
fprintf(stderr, "Insufficient memory (3).\n");
return;
}
for (i=0, p=CluQ.Head; p != NULL; i++, p=p->Next) {
CluArray[i] = p->Cluster;
}
Lim = CluQ.Count * BytesPerCluster;
if ((DirBuff = malloc(Lim)) == NULL) {
fprintf(stderr, "Insufficient memory for directory buffer.\n");
return;
}
for (i=0; i < CluQ.Count; i++) {
if (absread(Disk-'A', Dpb.ClusterSize + 1,
Alu2Sec(&Dpb, CluArray[i]),
(char *) &DirBuff[(i * BytesPerCluster) / 32])) {
fprintf(stderr, "Error reading directory.\n"); exit(1);
}
}
}
void WriteSub () {
extern struct ClusterQueue CluQ;
extern char Disk, *Fat, Parent[67], Element[13];
extern struct DpbStruct Dpb;
extern int Is12Bit, *CluArray, BytesPerCluster;
extern struct DirEntry *DirBuff;
int i;
for (i=0; i < CluQ.Count; i++) {
if (abswrite(Disk-'A', Dpb.ClusterSize + 1,
Alu2Sec(&Dpb, CluArray[i]),
(char *) &DirBuff[(i * BytesPerCluster) / 32])) {
fprintf(stderr, "Error writing directory.\n"); exit(1);
}
}
}
void ReadRoot () {
extern struct DpbStruct Dpb;
extern unsigned NumSec;
extern struct DirEntry *DirBuff;
extern int Is12Bit, *CluArray, Lim;
extern char Disk;
int i;
int Error;
Lim = Dpb.MaxEntries * 32;
NumSec = (Lim + Dpb.SectorSize - 1) / Dpb.SectorSize;
if ((DirBuff = malloc(Lim)) == NULL) {
fprintf(stderr, "Insufficient memory for cluster buffer.\n");
return;
}
if ((CluArray = malloc(sizeof(int))) == NULL) {
fprintf(stderr, "Insufficient memory (4).\n");
return;
}
CluArray[0] = 0;
if ((Error = absread(Disk-'A', NumSec, Dpb.DirStart, (char *) DirBuff)) != 0) {
fprintf(stderr, "Error reading root: %04X.\n", Error); exit(1);
}
}
void WriteRoot () {
extern char Disk;
extern unsigned Cluster, Sector, NumSec;
extern struct DpbStruct Dpb;
extern struct DirEntry *DirBuff;
if (abswrite(Disk-'A', NumSec, Dpb.DirStart, (char *) DirBuff)) {
fprintf(stderr, "Error writing Root.\n"); exit(1);
}
}